package cn.ug.pay.web.controller;

import cn.ug.aop.RequiresPermissions;
import cn.ug.bean.base.DataTable;
import cn.ug.bean.base.Order;
import cn.ug.bean.base.Page;
import cn.ug.bean.base.SerializeObject;
import cn.ug.bean.type.ResultType;
import cn.ug.config.Config;
import cn.ug.core.SerializeObjectError;
import cn.ug.core.login.LoginHelper;
import cn.ug.enums.RateKeyEnum;
import cn.ug.feign.MemberUserService;
import cn.ug.feign.RateSettingsService;
import cn.ug.member.bean.response.MemberUserBean;
import cn.ug.member.mq.MemberPasswordStatusMQ;
import cn.ug.mq.DelayMessagePostProcessor;
import cn.ug.pay.bean.MemberGoldBean;
import cn.ug.pay.bean.MemberGoldBeanBean;
import cn.ug.pay.bean.MemberGoldGroupByDayBean;
import cn.ug.pay.bean.SellGoldBean;
import cn.ug.pay.bean.type.BillGoldTradeType;
import cn.ug.pay.mapper.entity.PayAccountRecord;
import cn.ug.pay.mapper.entity.PayGoldStock;
import cn.ug.pay.service.GoldRecordService;
import cn.ug.pay.service.MemberGoldService;
import cn.ug.pay.service.PayAccountRecordService;
import cn.ug.pay.service.PayGoldStockService;
import cn.ug.util.BigDecimalUtil;
import cn.ug.util.ExportExcelUtil;
import cn.ug.util.PaginationUtil;
import cn.ug.util.UF;
import cn.ug.web.controller.BaseController;
import cn.ug.web.controller.ExportExcelController;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import static cn.ug.config.QueueName.QUEUE_MEMBER_PASSWORD_STATUS_DELAY;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

/**
 * 会员资产账户管理
 * @author kaiwotech
 */
@RestController
@RequestMapping("memberGold")
public class MemberGoldController extends BaseController {
    @Resource
    private MemberGoldService memberGoldService;
    @Resource
    private MemberUserService memberUserService;
    @Resource
    private GoldRecordService goldRecordService;
    @Autowired
    private PayGoldStockService payGoldStockService;
    @Resource
    private Config config;
    @Autowired
    private RateSettingsService rateSettingsService;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private PayAccountRecordService payAccountRecordService;

    @GetMapping(value = "/stock/list")
    public SerializeObject<DataTable<PayGoldStock>> listBuyGoldRecords(@RequestHeader String accessToken, Page page, String payDate) {
        payDate = UF.toString(payDate);
        int total = payGoldStockService.count(payDate);
        page.setTotal(total);
        if (total > 0) {
            List<PayGoldStock> list = payGoldStockService.query(payDate, PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()));
            return new SerializeObject<>(ResultType.NORMAL, new DataTable<PayGoldStock>(page.getPageNum(), page.getPageSize(), page.getTotal(), list));
        }
        return new SerializeObject<>(ResultType.NORMAL, new DataTable<PayGoldStock>(page.getPageNum(), page.getPageSize(), page.getTotal(), new ArrayList<PayGoldStock>()));
    }

    @GetMapping(value = "/stock/export")
    public void exportData(HttpServletResponse response, String payDate) {
        payDate = UF.toString(payDate);
        List<PayGoldStock> list = payGoldStockService.query(payDate, 0, 0);
        if(list != null && list.size() > 0){
            String[] columnNames = { "序号", "日期","黄金总资产（克）", "活期本金（克）", "活期利息（克）", "定期本金（克）", "定期预期收益（克）", "当日收盘价（元/克）"};
            String [] columns = {"index",  "calculationDate", "totalGram", "currentPrincipalGram", "currentInterestGram", "regularPrincipalGram", "regularInterestGram", "closingPrice"};
            String fileName = "黄金存量总表";
            int index = 1;
            for (PayGoldStock bean : list) {
                bean.setIndex(index);
                index++;
            }
            ExportExcelController<PayGoldStock> export = new ExportExcelController<PayGoldStock>();
            export.exportExcel(fileName, fileName, columnNames, columns, list, response, ExportExcelUtil.EXCEL_FILE_2003);
        }
    }

    @GetMapping(value = "/record/list")
    public SerializeObject<DataTable<PayAccountRecord>> listRecord(@RequestHeader String accessToken, Page page, String memberId, String startDate, String endDate) {
        startDate = UF.toString(startDate);
        endDate = UF.toString(endDate);
        memberId = UF.toString(memberId);
        int total = payAccountRecordService.count(memberId, startDate, endDate);
        page.setTotal(total);
        if (total > 0) {
            List<PayAccountRecord> list = payAccountRecordService.query(memberId, startDate, endDate, PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()));
            return new SerializeObject<>(ResultType.NORMAL, new DataTable<PayAccountRecord>(page.getPageNum(), page.getPageSize(), page.getTotal(), list));
        }
        return new SerializeObject<>(ResultType.NORMAL, new DataTable<PayAccountRecord>(page.getPageNum(), page.getPageSize(), page.getTotal(), new ArrayList<PayAccountRecord>()));
    }

    @GetMapping(value = "/record/export")
    public void exportData(HttpServletResponse response, String memberId, String startDate, String endDate) {
        startDate = UF.toString(startDate);
        endDate = UF.toString(endDate);
        memberId = UF.toString(memberId);
        List<PayAccountRecord> list = payAccountRecordService.query(memberId, startDate, endDate, 0, 0);
        if(list != null && list.size() > 0){
            String[] columnNames = { "日期","黄金总资产（克）", "活期本金（克）", "活期利息（克）", "定期本金（克）", "定期收益（克）"};
            String [] columns = {"addDate", "totalGram", "currentPrincipalGram", "currentInterestGram", "regularPrincipalGram", "regularInterestGram"};
            String fileName = "黄金账户表";
            ExportExcelController<PayAccountRecord> export = new ExportExcelController<PayAccountRecord>();
            export.exportExcel(fileName, fileName, columnNames, columns, list, response, ExportExcelUtil.EXCEL_FILE_2003);
        }
    }

    /**
     * 根据ID查找信息
     * @param id		    ID
     * @return			    记录集
     */
    @RequestMapping(value = "{id}", method = GET)
    public SerializeObject find(@PathVariable String id) {
        if(StringUtils.isBlank(id)) {
            return new SerializeObjectError("00000002");
        }
        MemberGoldBean entity = memberGoldService.findById(id);
        if(null == entity || StringUtils.isBlank(entity.getId())) {
            return new SerializeObjectError("00000003");
        }
        return new SerializeObject<>(ResultType.NORMAL, entity);
    }

    /**
     * 根据会员ID查找信息
     * @param memberId		会员ID
     * @return			    记录集
     */
    @RequestMapping(value = "memberId", method = GET)
    public SerializeObject findByMemberId(String memberId) {
        if(StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000002");
        }
        MemberGoldBean entity = memberGoldService.findByMemberId(memberId);
        if(null == entity || StringUtils.isBlank(entity.getId())) {
            return new SerializeObjectError("00000003");
        }
        // 昨日利息（前日的T日利息）
        BigDecimal yesterdayIncomeAmount = goldRecordService.yesterdayIncomeAmount(memberId);
        entity.setYesterdayIncomeAmount(yesterdayIncomeAmount);

        return new SerializeObject<>(ResultType.NORMAL, entity);
    }

    /**
     * 查询当前登录用户资产信息
     * @param accessToken		登录成功后分配的Key
     * @return			        记录集
     */
    @RequestMapping(value = "my", method = GET)
    public SerializeObject my(@RequestHeader String accessToken) {
        String memberId = LoginHelper.getLoginId();
        if(StringUtils.isBlank(memberId)) {
            return new SerializeObjectError<>("00000102");
        }
        return findByMemberId(memberId);
    }

    /**
     * 添加账户
     * @param accessToken		登录成功后分配的Key
     * @param entity		    记录集
     * @return				    是否操作成功
     */
    @RequiresPermissions("pay:memberGold:update")
    @RequestMapping(method = POST)
    public SerializeObject update(@RequestHeader String accessToken, MemberGoldBean entity) {
        if(null == entity || StringUtils.isBlank(entity.getMemberId())) {
            return new SerializeObjectError("00000002");
        }
        memberGoldService.save(entity);
        return new SerializeObject(ResultType.NORMAL, "00000001");
    }

    /**
     * 添加账户
     * @param memberId  会员ID
     * @return			是否操作成功
     */
    @RequestMapping(value = "create", method = POST)
    public SerializeObject create(String memberId) {
        if(StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000002");
        }
        MemberGoldBean entity = new MemberGoldBean();
        entity.setMemberId(memberId);
        memberGoldService.save(entity);
        return new SerializeObject(ResultType.NORMAL, "00000001");
    }

    /**
     * 查询数据
     * @param accessToken	        登录成功后分配的Key
     * @param order		            排序
     * @param page		            分页
     * @param amountMin		        最小黄金总资产
     * @param amountMax		        最大黄金总资产
     * @param usableAmountMin	    最小可用资产
     * @param usableAmountMax	    最大可用资产
     * @param freezeAmountMin	    最小冻结资产
     * @param freezeAmountMax	    最大冻结资产
     * @param turnIntoAmountMin	    最小转入资产
     * @param turnIntoAmountMax	    最大转入资产
     * @param turnOutAmountMin	    最小转出资产
     * @param turnOutAmountMax	    最大转出资产
     * @param addTimeMinString	    最小创建时间
     * @param addTimeMaxString	    最大创建时间
     * @param memberName	        会员名称
     * @param memberMobile	        会员手机
     * @param keyword		        关键字
     * @return			            分页数据
     */
    @RequestMapping(method = GET)
    public SerializeObject<DataTable<MemberGoldBean>> query(@RequestHeader String accessToken, Order order, Page page,
                                                            BigDecimal amountMin, BigDecimal amountMax,
                                                            BigDecimal usableAmountMin, BigDecimal usableAmountMax,
                                                            BigDecimal freezeAmountMin, BigDecimal freezeAmountMax,
                                                            BigDecimal turnIntoAmountMin, BigDecimal turnIntoAmountMax,
                                                            BigDecimal turnOutAmountMin, BigDecimal turnOutAmountMax,
                                                            String addTimeMinString, String addTimeMaxString,
                                                            String memberName, String memberMobile, String keyword) {
        if(page.getPageSize() <= 0) {
            page.setPageSize(config.getPageSize());
        }
        LocalDateTime addTimeMin = null;
        LocalDateTime addTimeMax = null;
        if(StringUtils.isNotBlank(addTimeMinString)) {
            addTimeMin = UF.getDate(addTimeMinString);
        }
        if(StringUtils.isNotBlank(addTimeMaxString)) {
            addTimeMax = UF.getDate(addTimeMaxString);
        }
        keyword = UF.toString(keyword);

        DataTable<MemberGoldBean> dataTable = memberGoldService.query(order.getOrder(), order.getSort(), page.getPageNum(), page.getPageSize(),
                amountMin, amountMax, usableAmountMin, usableAmountMax, freezeAmountMin, freezeAmountMax,
                turnIntoAmountMin, turnIntoAmountMax, turnOutAmountMin, turnOutAmountMax,
                addTimeMin, addTimeMax, memberName, memberMobile, keyword);
        return new SerializeObject<>(ResultType.NORMAL, dataTable);
    }

    /**
     * 查询当前登录用户金柚宝持有克重
     * @param accessToken	        登录成功后分配的Key
     * @return                      记录集
     */
    @RequestMapping(value = "viewUsableAmount", method = GET)
    public SerializeObject viewUsableAmount(@RequestHeader String accessToken) {
        String memberId = LoginHelper.getLoginId();
        if(StringUtils.isBlank(memberId)) {
            return new SerializeObjectError<>("00000102");
        }
        BigDecimal usableAmount = memberGoldService.viewUsableAmount(memberId);
        return new SerializeObject<>(ResultType.NORMAL, usableAmount);
    }

    /**
     * 卖金计算
     * @param accessToken	        登录成功后分配的Key
     * @param weight	            卖金克重
     * @return                      记录集
     */
    @RequestMapping(value = "sellGoldCalculate", method = GET)
    public SerializeObject sellGoldCalculate(@RequestHeader String accessToken, BigDecimal weight) {
        String memberId = LoginHelper.getLoginId();
        if(StringUtils.isBlank(memberId)) {
            return new SerializeObjectError<>("00000102");
        }
        SellGoldBean sellGoldBean = memberGoldService.sellGoldCalculate(memberId, weight);
        if(null == sellGoldBean) {
            return new SerializeObject<>(ResultType.ERROR);
        }
        return new SerializeObject<>(ResultType.NORMAL, sellGoldBean);
    }

    /**
     * 卖金
     * @param accessToken	        登录成功后分配的Key
     * @param weight	            卖金克重
     * @param payPassword		    交易密码
     * @return                      记录集
     */
    @RequestMapping(value = "sellGold", method = GET)
    public SerializeObject sellGold(@RequestHeader String accessToken, BigDecimal weight, String payPassword) {
        if(BigDecimalUtil.isZeroOrNull(weight) || StringUtils.isBlank(payPassword)) {
            return new SerializeObjectError("00000002");
        }
        if (weight.doubleValue() < 0) {
            return new SerializeObjectError("00000002");
        }
        String memberId = LoginHelper.getLoginId();
        if(StringUtils.isBlank(memberId)) {
            return new SerializeObjectError<>("00000102");
        }

        // 交易密码验证
        SerializeObject obj = memberUserService.validatePayPassword(memberId, payPassword);
        if(null == obj || obj.getCode() != ResultType.NORMAL) {
            info("交易密码验证失败。 memberId = " + memberId);
            SerializeObject paramBean  = rateSettingsService.get(RateKeyEnum.TRADE_PASSWORD.getKey());
            if (paramBean != null && paramBean.getData() != null) {
                JSONObject json = JSON.parseObject(JSONObject.toJSONString(paramBean.getData()));
                int isLimited = json.getIntValue("isLimited");
                int wrongTimes = json.getIntValue("wrongTimes");
                int minutes = json.getIntValue("minutes");
                if (isLimited == 1) {
                    SerializeObject<MemberUserBean> memberBean = memberUserService.findById(memberId);
                    if (null == memberBean || memberBean.getData() == null) {
                        return new SerializeObjectError("00000102");
                    }
                    MemberUserBean memberUserBean = memberBean.getData();
                    if (isLimited == 1 && memberUserBean.getTrdpassdStatus() == 1) {
                        SerializeObjectError result = new SerializeObjectError<>("17002034");
                        String msg = String.format(result.getMsg(), wrongTimes, minutes);
                        result.setMsg(msg);
                        return result;
                    }
                    int actualWrongTimes = memberUserBean.getTrdpassdWrongTimes();
                    actualWrongTimes++;
                    int status = 0;
                    if (wrongTimes <= actualWrongTimes) {
                        status = 1;
                    }
                    memberUserService.modifyWrongTimes(memberUserBean.getId(), 2, actualWrongTimes, status);
                    if (wrongTimes <= actualWrongTimes) {
                        MemberPasswordStatusMQ mq = new MemberPasswordStatusMQ();
                        mq.setMemberId(memberUserBean.getId());
                        mq.setType(2);
                        amqpTemplate.convertAndSend(QUEUE_MEMBER_PASSWORD_STATUS_DELAY, mq, new DelayMessagePostProcessor(minutes * 60 * 1000));

                        SerializeObjectError result = new SerializeObjectError<>("17002034");
                        String msg = String.format(result.getMsg(), wrongTimes, minutes);
                        result.setMsg(msg);
                        return result;
                    }
                }
            }
            return obj;
        }
        memberUserService.modifyWrongTimes(memberId, 2, 0, 0);
        weight = BigDecimalUtil.to5Point(weight);
        boolean isOk = memberGoldService.sellGold(memberId, weight);
        if(!isOk) {
            return new SerializeObject<>(ResultType.ERROR);
        }
        return new SerializeObject<>(ResultType.NORMAL);
    }

    /**
     * 赠送黄金
     * @param memberId	            会员ID
     * @param amount	            克重
     * @return                      记录集
     */
    @RequestMapping(value = "/gold/give", method = GET)
    public SerializeObject investRebate(String memberId, BigDecimal amount, int tradeType) {
        if(BigDecimalUtil.isZeroOrNull(amount) || StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000002");
        }
        BillGoldTradeType typeEnum = BillGoldTradeType.get(tradeType);
        if (typeEnum == null) {
            return new SerializeObjectError("00000002");
        }
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            return new SerializeObjectError("00000002");
        }
        info("赠送黄金 memberId = [" + memberId + "], amount = [" + amount + "]");
        memberGoldService.addPrincipalNowAmount(memberId, amount, typeEnum, null);
        return new SerializeObject<>(ResultType.NORMAL);
    }

    @RequestMapping(value = "/deduct", method = GET)
    public SerializeObject deductGold(String memberId, BigDecimal amount) {
        if(BigDecimalUtil.isZeroOrNull(amount) || StringUtils.isBlank(memberId)) {
            return new SerializeObjectError("00000002");
        }
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            return new SerializeObjectError("00000002");
        }
        info("扣除黄金克重 memberId = [" + memberId + "], amount = [" + amount + "]");
        memberGoldService.addPrincipalNowAmount(memberId, amount, BillGoldTradeType.REBATE, null);
        return new SerializeObject<>(ResultType.NORMAL);
    }

    /**
     * 转入转出详表
     * @param accessToken	        登录成功后分配的Key
     * @param page		            分页
     * @param memberId              会员ID
     * @return			            分页数据
     */
    @RequestMapping(value = "queryGroupByDay", method = GET)
    public SerializeObject<DataTable<MemberGoldGroupByDayBean>> queryGroupByDay(@RequestHeader String accessToken, Page page, String memberId) {
        if(page.getPageSize() <= 0) {
            page.setPageSize(config.getPageSize());
        }

        DataTable<MemberGoldGroupByDayBean> dataTable = memberGoldService.queryGroupByDay(page.getPageNum(), page.getPageSize(), memberId);
        return new SerializeObject<>(ResultType.NORMAL, dataTable);
    }

    @GetMapping(value = "/bean/list")
    public SerializeObject<DataTable<MemberGoldBeanBean>> queryForList(@RequestHeader String accessToken, Order order, Page page, String name, String mobile, Integer beanFrom, Integer beanTo, String startDate, String endDate) {
        name = UF.toString(name);
        mobile = UF.toString(mobile);
        startDate = UF.toString(startDate);
        endDate = UF.toString(endDate);
        beanFrom = beanFrom == null ? -1 : beanFrom;
        beanTo = beanTo == null ? -1 : beanTo;
        int total = memberGoldService.countForBean(name, mobile, beanFrom, beanTo, startDate, endDate);
        page.setTotal(total);
        if (total > 0) {
            List<MemberGoldBeanBean> list = memberGoldService.queryForBean(name, mobile, beanFrom, beanTo, startDate, endDate, order.getOrder(), order.getSort(), PaginationUtil.getOffset(page.getPageNum(), page.getPageSize()), PaginationUtil.getPageSize(page.getPageSize()));
            return new SerializeObject<>(ResultType.NORMAL, new DataTable<MemberGoldBeanBean>(page.getPageNum(), page.getPageSize(), page.getTotal(), list));
        }
        return new SerializeObject<>(ResultType.NORMAL, new DataTable<MemberGoldBeanBean>(page.getPageNum(), page.getPageSize(), page.getTotal(), new ArrayList<MemberGoldBeanBean>()));
    }

    @GetMapping(value = "/bean/export")
    public void exportData(HttpServletResponse response, Order order, String name, String mobile, Integer beanFrom, Integer beanTo, String startDate, String endDate) {
        name = UF.toString(name);
        mobile = UF.toString(mobile);
        startDate = UF.toString(startDate);
        endDate = UF.toString(endDate);
        beanFrom = beanFrom == null ? -1 : beanFrom;
        beanTo = beanTo == null ? -1 : beanTo;
        List<MemberGoldBeanBean> list = memberGoldService.queryForBean(name, mobile, beanFrom, beanTo, startDate, endDate, order.getOrder(), order.getSort(), 0, 0);
        if(list != null && !list.isEmpty()){
            String[] columnNames = { "序号", "手机号","用户姓名", "金豆总数（个）", "待收金豆（个）", "可用金豆（个）", "账户创建时间"};
            String [] columns = {"index",  "mobile", "name", "totalBean", "freezeBean", "usableBean", "addTime"};
            String fileName = "金豆账户管理表";
            int index = 1;
            for (MemberGoldBeanBean bean : list) {
                bean.setIndex(index);
                index++;
            }
            ExportExcelController<MemberGoldBeanBean> export = new ExportExcelController<MemberGoldBeanBean>();
            export.exportExcel(fileName, fileName, columnNames, columns, list, response, ExportExcelUtil.EXCEL_FILE_2003);
        }
    }
}
